From: Isaku Yamahata Date: Fri, 24 Oct 2008 04:49:58 +0000 (+0900) Subject: [IA64] Add glue code for VTD X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14060 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=5b89b6e99b533f6b7ae6ef1d0e2eae22dee57a94;p=xen.git [IA64] Add glue code for VTD Signed-off-by: Anthony Xu --- diff --git a/xen/arch/ia64/linux-xen/acpi.c b/xen/arch/ia64/linux-xen/acpi.c index 97ad0bbcc5..cc6ac3575a 100644 --- a/xen/arch/ia64/linux-xen/acpi.c +++ b/xen/arch/ia64/linux-xen/acpi.c @@ -797,6 +797,10 @@ int __init acpi_boot_init(void) if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt)) printk(KERN_ERR PREFIX "Can't find FADT\n"); +#ifdef XEN + acpi_dmar_init(); +#endif + #ifdef CONFIG_SMP if (available_cpus == 0) { printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n"); diff --git a/xen/arch/ia64/vmx/viosapic.c b/xen/arch/ia64/vmx/viosapic.c index cf3bf9955d..8922fbe2dc 100644 --- a/xen/arch/ia64/vmx/viosapic.c +++ b/xen/arch/ia64/vmx/viosapic.c @@ -121,6 +121,13 @@ static void viosapic_update_EOI(struct viosapic *viosapic, int vector) redir_num, vector); return; } + if ( iommu_enabled ) + { + spin_unlock(&viosapic->lock); + hvm_dpci_eoi(current->domain, redir_num, &viosapic->redirtbl[redir_num]); + spin_lock(&viosapic->lock); + } + service_iosapic(viosapic); spin_unlock(&viosapic->lock); } diff --git a/xen/arch/ia64/vmx/vmx_fault.c b/xen/arch/ia64/vmx/vmx_fault.c index 5a6ed0a163..e1365aa4a0 100644 --- a/xen/arch/ia64/vmx/vmx_fault.c +++ b/xen/arch/ia64/vmx/vmx_fault.c @@ -54,6 +54,7 @@ #include #include #include +#include /* reset all PSR field to 0, except up,mfl,mfh,pk,dt,rt,mc,it */ #define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034 @@ -306,6 +307,7 @@ void leave_hypervisor_tail(void) viosapic_set_irq(d, callback_irq, 0); } } + hvm_dirq_assist(v); } rmb(); diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 679d0c3a9a..68b243a9de 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -602,6 +602,11 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) if ((d->arch.mm.pgd = pgd_alloc(&d->arch.mm)) == NULL) goto fail_nomem; + if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ){ + if(iommu_domain_init(d) != 0) + goto fail_iommu; + } + /* * grant_table_create() can't fully initialize grant table for domain * because it is called before arch_domain_create(). @@ -618,6 +623,8 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) dprintk(XENLOG_DEBUG, "arch_domain_create: domain=%p\n", d); return 0; +fail_iommu: + iommu_domain_destroy(d); fail_nomem: tlb_track_destroy(d); fail_nomem1: @@ -637,6 +644,11 @@ void arch_domain_destroy(struct domain *d) free_xenheap_pages(d->shared_info, get_order_from_shift(XSI_SHIFT)); + if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ) { + pci_release_devices(d); + iommu_domain_destroy(d); + } + tlb_track_destroy(d); /* Clear vTLB for the next domain. */ diff --git a/xen/arch/ia64/xen/irq.c b/xen/arch/ia64/xen/irq.c index 2c250148c5..e3c3da3b08 100644 --- a/xen/arch/ia64/xen/irq.c +++ b/xen/arch/ia64/xen/irq.c @@ -312,12 +312,25 @@ typedef struct { struct domain *guest[IRQ_MAX_GUESTS]; } irq_guest_action_t; +static struct timer irq_guest_eoi_timer[NR_IRQS]; +static void irq_guest_eoi_timer_fn(void *data) +{ + irq_desc_t *desc = data; + unsigned vector = desc - irq_desc; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + desc->status &= ~IRQ_INPROGRESS; + desc->handler->enable(vector); + spin_unlock_irqrestore(&desc->lock, flags); +} + void __do_IRQ_guest(int irq) { irq_desc_t *desc = &irq_desc[irq]; irq_guest_action_t *action = (irq_guest_action_t *)desc->action; struct domain *d; - int i; + int i, already_pending = 0; for ( i = 0; i < action->nr_guests; i++ ) { @@ -325,8 +338,29 @@ void __do_IRQ_guest(int irq) if ( (action->ack_type != ACKTYPE_NONE) && !test_and_set_bit(irq, &d->pirq_mask) ) action->in_flight++; - send_guest_pirq(d, irq); - } + if ( hvm_do_IRQ_dpci(d, irq) ) + { + if ( action->ack_type == ACKTYPE_NONE ) + { + already_pending += !!(desc->status & IRQ_INPROGRESS); + desc->status |= IRQ_INPROGRESS; /* cleared during hvm eoi */ + } + } + else if ( send_guest_pirq(d, irq) && + (action->ack_type == ACKTYPE_NONE) ) + { + already_pending++; + } + } + + if ( already_pending == action->nr_guests ) + { + desc->handler->disable(irq); + stop_timer(&irq_guest_eoi_timer[irq]); + init_timer(&irq_guest_eoi_timer[irq], + irq_guest_eoi_timer_fn, desc, smp_processor_id()); + set_timer(&irq_guest_eoi_timer[irq], NOW() + MILLISECS(1)); + } } int pirq_acktype(int irq) diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index 9cf861f5eb..0ccd756046 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -1435,6 +1435,8 @@ zap_domain_page_one(struct domain *d, unsigned long mpaddr, if (mfn == INVALID_MFN) { // clear pte old_pte = ptep_get_and_clear(mm, mpaddr, pte); + if(!pte_mem(old_pte)) + return; mfn = pte_pfn(old_pte); } else { unsigned long old_arflags; @@ -1472,6 +1474,13 @@ zap_domain_page_one(struct domain *d, unsigned long mpaddr, if(!mfn_valid(mfn)) return; + if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ){ + int i, j; + j = 1 << (PAGE_SHIFT-PAGE_SHIFT_4K); + for(i = 0 ; i < j; i++) + iommu_unmap_page(d, (mpaddr>>PAGE_SHIFT)*j + i); + } + page = mfn_to_page(mfn); BUG_ON((page->count_info & PGC_count_mask) == 0); @@ -2856,6 +2865,12 @@ __guest_physmap_add_page(struct domain *d, unsigned long gpfn, smp_mb(); assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, ASSIGN_writable | ASSIGN_pgc_allocated); + if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ){ + int i, j; + j = 1 << (PAGE_SHIFT-PAGE_SHIFT_4K); + for(i = 0 ; i < j; i++) + iommu_map_page(d, gpfn*j + i, mfn*j + i); + } } int diff --git a/xen/include/asm-ia64/linux-xen/asm/acpi.h b/xen/include/asm-ia64/linux-xen/asm/acpi.h index f59db9202e..7a66a0c124 100644 --- a/xen/include/asm-ia64/linux-xen/asm/acpi.h +++ b/xen/include/asm-ia64/linux-xen/asm/acpi.h @@ -38,6 +38,7 @@ #include #ifdef XEN #include +extern int acpi_dmar_init(void); #endif #define COMPILER_DEPENDENT_INT64 long diff --git a/xen/include/asm-ia64/linux-xen/asm/iosapic.h b/xen/include/asm-ia64/linux-xen/asm/iosapic.h index d3d68ef082..46dd30ec53 100644 --- a/xen/include/asm-ia64/linux-xen/asm/iosapic.h +++ b/xen/include/asm-ia64/linux-xen/asm/iosapic.h @@ -83,12 +83,25 @@ static inline int find_iosapic_by_addr(unsigned long addr) static inline unsigned int iosapic_read(char __iomem *iosapic, unsigned int reg) { +#ifdef XEN + if(iommu_enabled && (reg >= 10)){ + int apic = find_iosapic_by_addr((unsigned long)iosapic); + return io_apic_read_remap_rte(apic, reg); + } +#endif writel(reg, iosapic + IOSAPIC_REG_SELECT); return readl(iosapic + IOSAPIC_WINDOW); } static inline void iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) { +#ifdef XEN + if (iommu_enabled && (reg >= 10)){ + int apic = find_iosapic_by_addr((unsigned long)iosapic); + iommu_update_ire_from_apic(apic, reg, val); + return; + } +#endif writel(reg, iosapic + IOSAPIC_REG_SELECT); writel(val, iosapic + IOSAPIC_WINDOW); } diff --git a/xen/include/asm-ia64/viosapic.h b/xen/include/asm-ia64/viosapic.h index c334ea0c60..7004e6e5b9 100644 --- a/xen/include/asm-ia64/viosapic.h +++ b/xen/include/asm-ia64/viosapic.h @@ -70,5 +70,7 @@ void viosapic_write(struct vcpu *v, unsigned long addr, unsigned long viosapic_read(struct vcpu *v, unsigned long addr, unsigned long length); +void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi, + union vioapic_redir_entry *ent); #endif /* __ASM_IA64_VMX_VIOSAPIC_H__ */